#pragma once
#include "loggerstream.h"
#include "../timestamp.h"
#include "../currentThread.h"
#include <stdio.h>
#include <sstream>
#include <string>
namespace TinyRPC{
    
#define LOG_SET_LEVEL(level) \
    TinyRPC::Logger::GetInstance().setLogLevel(level)

#define LOG_INFO \
    if( TinyRPC::Logger::GetInstance().getLogLevel() <= TinyRPC::LogLevel::INFO )  \
        TinyRPC::LoggerWrapper(TinyRPC::Logger::GetInstance()).getSStream(__FILE__, (const char*)__FUNCTION__, __LINE__,  TinyRPC::CurrentThread::Tid(), TinyRPC::LogLevel::INFO) 

#define LOG_DEBUG \
    if( TinyRPC::Logger::GetInstance().getLogLevel() <= TinyRPC::LogLevel::DEBUG )  \
        TinyRPC::LoggerWrapper(TinyRPC::Logger::GetInstance()).getSStream(__FILE__, (const char*)__FUNCTION__, __LINE__,  TinyRPC::CurrentThread::Tid(), TinyRPC::LogLevel::DEBUG) 

#define LOG_WARNING \
    if( TinyRPC::Logger::GetInstance().getLogLevel() <= TinyRPC::LogLevel::WARNING )  \
        TinyRPC::LoggerWrapper(TinyRPC::Logger::GetInstance()).getSStream(__FILE__, (const char*)__FUNCTION__, __LINE__,  TinyRPC::CurrentThread::Tid(), TinyRPC::LogLevel::WARNING) 

#define LOG_ERROR \
    if(TinyRPC::Logger::GetInstance().getLogLevel() <= TinyRPC::LogLevel::ERROR )  \
        TinyRPC::LoggerWrapper(TinyRPC::Logger::GetInstance()).getSStream(__FILE__, (const char*)__FUNCTION__, __LINE__,   TinyRPC::CurrentThread::Tid(), TinyRPC::LogLevel::ERROR) 

enum LogLevel{
    DEBUG = 0,
    INFO = 1,
    WARNING = 2,
    ERROR = 3 
};

char* GetLevelName(LogLevel level);

class Logger{
public:
    static Logger& GetInstance();
    
    void setLogLevel(LogLevel level);
    LogLevel getLogLevel();

    void log(std::string& str);
    void log(std::string&& str);

    // 为全局日志类设置日志等级
    static void SetLogLevel(LogLevel level);
private:
    Logger(LogLevel level);
    ~Logger();
private:
    
    LogLevel m_level;
    std::ofstream m_ofs;
    LogStream m_logStream;

    // 全局日志类
    static Logger g_logger;
};


    

// 定义一个包装类, 其生命周期是用来控制日志的输出
class LoggerWrapper{
public:
    LoggerWrapper(Logger & logger);
    ~LoggerWrapper();
    std::stringstream& getSStream(const char* fileNmae, const char* funcName, int lineNo, pid_t tid, LogLevel level);
private:
    std::stringstream m_ss;
    Logger & m_logger;

};
}
